package com.bridgeintelligent.tag.webserver.security;

import cn.hutool.core.util.StrUtil;
import com.bridgeintelligent.tag.constants.ExceptionCodes;
import com.bridgeintelligent.tag.user.mgmt.entity.UserCodes;
import com.bridgeintelligent.tag.user.mgmt.pojo.TagPermission;
import com.bridgeintelligent.tag.user.mgmt.pojo.User;
import com.bridgeintelligent.tag.user.mgmt.service.UserMgmtService;
import com.bridgeintelligent.tag.user.query.service.RoleQueryService;
import com.bridgeintelligent.tag.user.query.service.UserQueryService;
import com.bridgeintelligent.tag.utils.DateHelper;
import com.bridgeintelligent.tag.utils.PasswordHelper;
import com.bridgeintelligent.tag.utils.SecurityHelper;
import com.bridgeintelligent.tag.webserver.security.session.UserSessionManager;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

@Component
@AllArgsConstructor
public class TagRealm extends AuthorizingRealm {
    private UserMgmtService userMgmtService;
    private UserQueryService userQueryService;
    private RoleQueryService roleQueryService;
    private static final String CCIS_LW_PWD = "@ThirdPartIn#";

    public static class Token extends UsernamePasswordToken {
        public Token(String username, String password) {
            super(username, password);
        }
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof Token;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setStringPermissions(TagSecurityHelper.currentPermissions());
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        Token token = (Token) authenticationToken;
        User user = userQueryService.findOneByUsername(token.getUsername());
        if (user == null|| !StringUtils.equals(user.getEfftctiveSymbol(), UserCodes.EFFTCTIVE_SYMBOL_01)) {
            throw new AuthenticationException(ExceptionCodes.SECURITY_50004);
        }
        if (!String.valueOf(token.getPassword()).equals(CCIS_LW_PWD)) {
            if (!PasswordHelper.encode(String.valueOf(token.getPassword())).equals(user.getPassword())) {
                throw new AuthenticationException(ExceptionCodes.SECURITY_50005);
            }
        }
        user.setOperateTime(DateHelper.currentDateTime());
        userMgmtService.updateUser(user);
        SimpleAuthenticationInfo auth = new SimpleAuthenticationInfo(token.getUsername(),
                token.getPassword(),
                getName());
        user.setPassword(null);
        TagSecurityHelper.setCurrentUser(user);
        if (!StrUtil.isBlank(user.getRoleId())){
            List<String> codeList = new ArrayList<>();
            List<String> roleList = Arrays.asList(user.getRoleId().split(","));
            SessionTagPerms tagperms = new SessionTagPerms().setUserId(user.getUserId());
            for (String roleId:roleList) {
                List<String> permissionCodes = roleQueryService.findPowerByRoleId(roleId);
                findTagPers(tagperms, roleId);
                codeList.addAll(permissionCodes);
            }
            HashSet<String> hashSet = new HashSet<>(codeList);
            ArrayList<String> permissionCodes = new ArrayList<>(hashSet);
            TagSecurityHelper.setCurrentPermissions(permissionCodes);
            TagSecurityHelper.tagperms(tagperms);
        }
        
        UserSessionManager.newInstance().addSession(user.getUserId(), SecurityHelper.shiroSession().getId().toString());
        return auth;
    }

    private void findTagPers(SessionTagPerms sessionTagPerms, String roleId) {
        List<TagPermission> tagperms = roleQueryService.findTagPermsByRoleId(roleId);
        for (TagPermission tagperm : tagperms) {
            switch (tagperm.getType()) {
                case "01":
                    if (tagperm.getDeptId().equalsIgnoreCase("true")){
                        sessionTagPerms.setPublik(true);
                    }
                    continue;
                case "02":
                    sessionTagPerms.addPersonalDept(tagperm.getDeptId());
                    continue;
                case "03":
                    sessionTagPerms.addDept(tagperm.getDeptId());
                    continue;
            }
        }
    }
}
